package com.woate.wingframework.test.persistence.utils;

import com.woate.wingframework.annotations.runtime.persistence.Comment;
import com.woate.wingframework.test.persistence.metadata.ColumnMetadata;
import com.woate.wingframework.test.persistence.metadata.TableMetadata;

import javax.persistence.*;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * 实体工具类，用于从实体类上提取注解，生成封装
 */
public abstract class EntityUtils {
    /**
     * 从实体类中提取表名
     *
     * @param entityClass
     * @return
     */
    public static TableMetadata extractTable(Class entityClass) {
        Table table = (Table) entityClass.getAnnotation(Table.class);
        Comment comment = (Comment) entityClass.getAnnotation(Comment.class);
        if (table != null && table.name() != null && table.name().trim().length() > 0) {
            String commentStr = comment == null ? "" : comment.value();
            TableMetadata tableVO = new TableMetadata(table.name(), commentStr);
            return tableVO;
        } else {
            throw new IllegalArgumentException();
        }
    }

    public static Map<String, ColumnMetadata> extractFields(Class entityClass) {
        Field[] fields = entityClass.getDeclaredFields();
        Map<String, ColumnMetadata> fieldsMap = new LinkedHashMap();
        for (Field field : fields) {
            Column column = field.getAnnotation(Column.class);
            if (column != null) {
                ColumnMetadata columnVO = extractField(field);
                fieldsMap.put(columnVO.getJdbcName(), columnVO);
            }
        }
        return fieldsMap;
    }

    public static List<String> extractPrimaryKey(Class entityClass) {
        Field[] fields = entityClass.getDeclaredFields();
        List<String> pks = new ArrayList<String>();
        for (Field field : fields) {
            Id id = field.getAnnotation(Id.class);
            Column column = field.getAnnotation(Column.class);
            if (id != null && column != null) {
                pks.add(column.name());
            }
        }
        return pks;
    }

    public static ColumnMetadata extractField(Field field) {
        Column column = field.getAnnotation(Column.class);
        Comment comment = field.getAnnotation(Comment.class);
        String jdbcName = column.name();
        String commentStr = comment == null ? "" : comment.value();
        int precision = column.precision();
        int scale = column.scale();
        boolean nullable = column.nullable();
        String dataType = null;
        String jdbcType = null;
        Class fieldClass = field.getType();
        if (fieldClass == BigDecimal.class) {
            if (scale > 0 && precision > 0) {
                dataType = "DECIMAL(" + scale + "," + precision + ")";

            } else if (scale > 0 && precision == 0) {
                dataType = "DECIMAL(" + scale + ")";
            } else if (scale == 0 && precision > 0) {
                dataType = "DECIMAL(18," + scale + ")";
            } else {
                dataType = "DECIMAL(18,2)";
            }
            jdbcType = "DECIMAL";

        } else if (fieldClass == Integer.class || fieldClass == Integer.TYPE) {
            dataType = "NUMERIC";
            jdbcType = "NUMERIC";
        } else if (fieldClass == String.class) {
            if (scale > 0) {
                dataType = "VARCHAR(" + scale + ")";
                jdbcType = "VARCHAR";
            } else {
                throw new IllegalArgumentException("字段[" + jdbcName + "]为VARCHAR类型，但是没有指定scale");
            }
        } else if (fieldClass == java.util.Date.class) {
            Temporal temporal = field.getAnnotation(Temporal.class);
            //如果没有注解则直接使用DATETIME
            if (temporal == null) {
                dataType = "DATETIME";
                jdbcType = "DATE";
            } else {
                //如果有注解指定数据类型，则使用指定的数据类型
                if (TemporalType.TIMESTAMP == temporal.value()) {
                    dataType = "TIMESTAMP";
                    jdbcType = "TIMESTAMP";
                } else if (TemporalType.TIME == temporal.value()) {
                    dataType = "TIME";
                    jdbcType = "TIME";
                } else {
                    dataType = "DATETIME";
                    jdbcType = "DATE";
                }
            }
        } else if (fieldClass == java.sql.Timestamp.class) {
            dataType = "TIMESTAMP";
            jdbcType = "TIMESTAMP";
        }
        ColumnMetadata columnVO = new ColumnMetadata(field.getName(),jdbcName, dataType, jdbcType, nullable, commentStr);
        return columnVO;
    }
}
